//    Copyright (C) Kherty.  All rights reserved.
using System.Windows.Media.Media3D;

namespace OpenLS.Chart.UI
{
    abstract class PyramidBaseGeometryFactory : MeshGeometryFactory
    {
        protected PyramidBaseGeometryFactory(BarDirection direction): base (direction)
        { 
        }
        public override MeshGeometry3D CreateGeometry(Bounds3D bounds, Bounds totalValueBounds2, double floor)
        {
            MeshGeometry3D result = new MeshGeometry3D();
            this.bounds = bounds;
            this.totalValueBounds = totalValueBounds2;
            Bounds categoryBounds = GetCategoryBounds(bounds);
            Bounds valueBounds = GetValueBounds(bounds);
            Point3D high1 = newPoint3D(valueBounds.High, categoryBounds.Low, bounds.Z.Low);
            Point3D high2 = newPoint3D(valueBounds.High, categoryBounds.Low, bounds.Z.High);
            Point3D high3 = newPoint3D(valueBounds.High, categoryBounds.High, bounds.Z.High);
            Point3D high4 = newPoint3D(valueBounds.High, categoryBounds.High, bounds.Z.Low);
            Point3D low1 = newPoint3D(valueBounds.Low, categoryBounds.Low, bounds.Z.Low);
            Point3D low2 = newPoint3D(valueBounds.Low, categoryBounds.Low, bounds.Z.High);
            Point3D low3 = newPoint3D(valueBounds.Low, categoryBounds.High, bounds.Z.High);
            Point3D low4 = newPoint3D(valueBounds.Low, categoryBounds.High, bounds.Z.Low);
            bool backSide = Direction == BarDirection.Bar;
            Tessellator.Tessellate(result, backSide, high1, high2, high3, high4);
            Tessellator.Tessellate(result, backSide, low4, low3, low2, low1);

            Tessellator.Tessellate(result, backSide, low1, low2, high2, high1);
            Tessellator.Tessellate(result, backSide, low2, low3, high3, high2);
            Tessellator.Tessellate(result, backSide, low3, low4, high4, high3);
            Tessellator.Tessellate(result, backSide, low4, low1, high1, high4);
            result.Freeze();
            return result;
        }

        protected Bounds3D bounds;
        protected Bounds totalValueBounds;
        Point3D newPoint3D(double value, double category, double z)
        {
            return TransformPoint(CreatePoint(value, category, z));
        }

        protected abstract Point3D TransformPoint(Point3D point);

        protected virtual double GetPoint(double value, double mid, double yvalue, double min, double max)
        {
            return mid + (value - mid) * (max - yvalue) / (max - min);
        }
    }
}
